
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.util.Random;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
/**
 *
 * @author Russell
 */
public class MainClass {

    private String[] name;
    private String[] location;
    private int numConnections;
    private int port;
    private String myName;
    public Socket socket;
    public BufferedReader receiveText;
    public DataOutputStream sendMessage;
    public DataInputStream newMessageIn;
    public ServerSocket listenSocket;
    public int myId;
    public String input;
    public int myNonce;
    public int peerNonce;
    public String[] inputArray;
    public ByteBuffer byteBuffer;

    public MainClass(int id) throws IOException, UnknownHostException, InterruptedException {
        this.myId = id;
        ReadFile systemFile = new ReadFile(new File("system.properties")); // read in file and get system info
        this.numConnections = systemFile.getNumConnections();
        this.name = new String[numConnections];
        this.location = new String[numConnections];
        this.name = systemFile.getName();
        this.location = systemFile.getLocation();
        this.port = systemFile.getPort();
        this.input = "default";
        this.myName = "hi";
        this.listenSocket = new ServerSocket(this.port);

        for (int i = 0; i < this.numConnections; i++) {
            if (i == this.myId) {
                this.myName = this.name[i];
            }
        }

        initiateSession();
        
        // send data

        this.socket.close();
    }
    
    public int getRandom(){
        Random random = new Random();
        int temp = random.nextInt(64000);
        return temp;
    }

    public void writeToLog(String direction, String line) throws IOException {
        FileWriter fStream = new FileWriter(this.myName + ".log", true);
        BufferedWriter logFile = new BufferedWriter(fStream);
        logFile.write(direction + ": " + line);
        logFile.newLine();
        logFile.close();
    }
    
    public static int byteToInt(byte[] bytes, int size) {
        int result = 0;
        for (int i = 0; i < size; i++) {
            result = (result << 8) + (int) (bytes[i]&0xFF);
        }
        return result;
    }

    public void initiateSession() throws UnknownHostException, IOException, InterruptedException {
        this.myNonce = getRandom();
        byteBuffer = ByteBuffer.allocate(4);
        byteBuffer.putInt(this.myNonce);
        byte[] nonceBytes = new byte[4];
        nonceBytes = byteBuffer.array();


        if (this.myName.equals("Alice")) {
            String key = "mykey%^345";
            String ciphers = "RC4, CFB, CBC, PCBC";
            
            RsaEncryption modeOne = new RsaEncryption("Bob", true, key.getBytes());
            String sessionKey = modeOne.getCipherString();
            byte[] sessionKeyBytes = modeOne.getCipherArray();
            
            Thread.sleep(1000);
            
            this.socket = new Socket(this.location[1], this.port);
            this.sendMessage = new DataOutputStream(this.socket.getOutputStream());
            this.newMessageIn = new DataInputStream(this.socket.getInputStream());
            this.receiveText = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));

            writeToLog("send", ciphers + "," + this.myNonce);
            
            this.sendMessage.writeBytes(ciphers + "\n");     
            
            this.receiveText.readLine();
            
            modeOne = new RsaEncryption("Bob", true, nonceBytes);
            byte[] nonceEncryptedBytes = modeOne.getCipherArray();
            this.sendMessage.write(nonceEncryptedBytes);
            
            input = this.receiveText.readLine();
            
            this.sendMessage.writeBytes("ack \n");
            
            byte[] nonce = new byte[4];
            int receiveBytes = this.newMessageIn.read(nonce, 0, 4);
            modeOne = new RsaEncryption("Alice", false, nonce);
            nonce = modeOne.getCipherArray();
            this.peerNonce = byteToInt(nonce, 4);
            
            writeToLog("receive", input + ", Bob's nonce = " + this.peerNonce);
            
            writeToLog("send", "key:" + key + ", K(keyed hash of msgs)");
            
            this.sendMessage.write(sessionKeyBytes);
            
            input = this.receiveText.readLine();
            
            writeToLog("receive", input);
    
        }

        if (this.myName.equals("Bob")) {
            this.socket = listenSocket.accept();
            this.sendMessage = new DataOutputStream(this.socket.getOutputStream());
            this.newMessageIn = new DataInputStream(this.socket.getInputStream());
            this.receiveText = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
            
            input = this.receiveText.readLine();
                      
            this.sendMessage.writeBytes("ack \n");
                     
            byte[] nonce = new byte[4];
            int receiveBytes = this.newMessageIn.read(nonce, 0, 4);
            RsaEncryption modeTwo = new RsaEncryption("Bob", false, nonce);
            nonce = modeTwo.getCipherArray();
            this.peerNonce = byteToInt(nonce, 4);
     
            writeToLog("receive", input + ", Alice's nonce = " + this.peerNonce);
            
            writeToLog("send","id 1, my cert, rc4, " + this.myNonce);
            
            this.sendMessage.writeBytes("id 1, my cert, rc4, \n");
            
            this.receiveText.readLine();
            
                        
            modeTwo = new RsaEncryption("Alice", true, nonceBytes);
            byte[] nonceEncryptedBytes = modeTwo.getCipherArray();
            this.sendMessage.write(nonceEncryptedBytes);

            int tempSize = 10; //this.newMessageIn.available();
            byte[] pieceByte = new byte[tempSize];
            receiveBytes = this.newMessageIn.read(pieceByte, 0, tempSize);
            RsaEncryption decryptKey = new RsaEncryption("Bob", false, pieceByte);
            String sessionKey = decryptKey.getCipherString();
            
            writeToLog("receive ", "key: " + sessionKey);

            writeToLog("send","keyed hash of msgs \n");
            
            this.sendMessage.writeBytes("keyed hash of msgs \n");

        }
    }

    public void rsaEncryption() {
    }

    public void rsaDecryption() {
    }
}
